<script setup>
import { computed, ref, watch, onMounted } from "vue";
import { parseBlob } from 'music-metadata';
import emitter from "@/utils/EventBus.js";

const props = defineProps({
  url: {
    required: true,
    type: String
  }
})

const musicData = ref({
  album: null,
  artist: null,
  artists: [],
  title: null,
  year: null,
  genre: [],
  track: null,
  picture: null
})

const audioElement = ref()
const coverImage = ref(null)
const loading = ref(false)
const error = ref(null)

const displayArtist = computed(() => {
  if (musicData.value.artists?.length > 0) {
    return musicData.value.artists.join(', ')
  }
  return musicData.value.artist || '未知艺术家'
})

const displayTitle = computed(() => {
  return musicData.value.title || '未知标题'
})

const displayAlbum = computed(() => {
  return musicData.value.album || '未知专辑'
})

const fetchMetadata = async (url) => {
  if (!url) return

  loading.value = true
  error.value = null

  try {
    // console.log('fetch audio:', url)
    const response = await fetch(url)
    if (!response.ok) {
      throw new Error(`cant not get: ${response.status}`)
    }

    const blob = await response.blob()
    const metadata = await parseBlob(blob)

    // console.log('parsed data:', metadata)

    musicData.value = {
      album: metadata.common.album,
      artist: metadata.common.artist,
      artists: metadata.common.artists || [],
      title: metadata.common.title,
      year: metadata.common.year || '',
      genre: metadata.common.genre || [],
      track: metadata.common.track,
      picture: metadata.common.picture?.[0] || null
    }

    if (metadata.common.picture?.[0]) {
      const picture = metadata.common.picture[0]
      const blob = new Blob([picture.data], { type: picture.format })
      coverImage.value = URL.createObjectURL(blob)
    } else {
      coverImage.value = null
    }

  } catch (err) {
    console.error('parse failed:', err)
    error.value = err.message

    musicData.value = {
      album: null,
      artist: null,
      artists: [],
      title: null,
      year: null,
      genre: [],
      track: null,
      picture: null
    }
    coverImage.value = null
  } finally {
    loading.value = false
  }
}


const cleanup = () => {
  if (coverImage.value) {
    URL.revokeObjectURL(coverImage.value)
    coverImage.value = null
  }
}

watch(
    () => props.url,
    (newUrl, oldUrl) => {
      if (newUrl !== oldUrl) {
        cleanup()
        fetchMetadata(newUrl)
      }
    },
    { immediate: true }
)


onMounted(() => {
  audioElement.value.addEventListener('play', ()=> {
    emitter.emit('stop audio', props.url)
  })

  emitter.on('stop audio', (url)=>{
    if (props.url !== url) {
      audioElement.value.pause()
    }
  })
  return () => cleanup()
})
</script>

<template>
  <div class="card border-0 shadow-sm bg-dark-subtle" style="max-width: 320px; min-width: 80px; width: 320px">
    <div class="card-body p-3">

      <div v-if="loading" class="text-center py-3">
        <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
        <small class="d-block text-muted mt-2">加载中...</small>
      </div>


      <div v-else-if="error" class="alert alert-warning mb-3">
        <i class="bi bi-exclamation-triangle me-1"></i>
        <small>{{ error }}</small>
      </div>

      <div v-else class="d-flex flex-wrap gap-3 mb-3">
        <div class="flex-shrink-0">
          <img
              v-if="coverImage"
              :src="coverImage"
              class="rounded"
              style="width: 84px; height: 84px; object-fit: cover;"
          />
          <div
              v-else
              class="bg-secondary-subtle d-flex align-items-center justify-content-center rounded"
              style="width: 84px; height: 84px;"
          >
            <font-awesome-icon :icon="['fas', 'music']" size="xl" />
          </div>
        </div>

        <div class="flex-grow-1 min-w-0 overflow-hidden">
          <h6 class="mb-1 text-truncate">{{ displayTitle }}</h6>
          <p class="text-muted mb-1 small text-truncate">{{ displayArtist }}</p>
          <div class="d-flex gap-1">
            <span v-if="musicData.year" class="badge bg-secondary">{{ musicData.year }}</span>
            <span v-if="musicData.genre?.length" class="badge bg-info">{{ musicData.genre[0] }}</span>
          </div>
        </div>
      </div>

      <audio controls class="w-100" ref="audioElement" :src="props.url" style="height: 32px;"></audio>
    </div>
  </div>
</template>

<style scoped>
audio {
  border-radius: 0.375rem;
}

.text-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 575.98px) {
  .card {
    max-width: 100% !important;
  }
}
</style>